using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Zhaoxi.Zhihu.Core.Common;
using Zhaoxi.Zhihu.UseCases.Common.Interface;

namespace Zhaoxi.Zhihu.Infrastructure.Interceptors;

public class AuditEntityInterceptor(IUser currentUser) : SaveChangesInterceptor
{
    public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
    {
        UpdateEntities(eventData.Context);

        return base.SavingChanges(eventData, result);
    }

    public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData,
        InterceptionResult<int> result,
        CancellationToken cancellationToken = default)
    {
        UpdateEntities(eventData.Context);

        return base.SavingChangesAsync(eventData, result, cancellationToken);
    }

    private void UpdateEntities(DbContext? eventDataContext)
    {
        if (eventDataContext == null) return;

        foreach (var entity in eventDataContext.ChangeTracker.Entries<BaseAuditEntity>())
        {
            if (entity.State is not (EntityState.Added or EntityState.Modified)) continue;

            var utcNow = DateTimeOffset.UtcNow;

            if (entity.State == EntityState.Added)
                entity.Entity.CreateAt = utcNow;
            else
                entity.Entity.LastModifiedAt = utcNow;
        }

        foreach (var entity in eventDataContext.ChangeTracker.Entries<AuditWithUserEntity>())
        {
            if (entity.State is not (EntityState.Added or EntityState.Modified)) continue;

            if (currentUser.Id is null) continue;

            if (entity.State == EntityState.Added)
                entity.Entity.CreatedBy = currentUser.Id;
            else
                entity.Entity.LastModifiedBy = currentUser.Id;
        }
    }
}